<template>
    <div class="container">
        <div class="operateblock">
            <el-form :inline="true" :model="state.formInline" class="demo-form-inline" ref="operateRef">
                <el-form-item prop="searchVal">
                    <el-input v-model="state.formInline.searchVal" placeholder="菜单名称" />
                </el-form-item>
                <el-form-item label="菜单状态" prop="state">
                    <el-select v-model="state.formInline.state">
                        <el-option label="全部" :value="0" />
                        <el-option label="正常" :value="1" />
                        <el-option label="停用" :value="2" />
                    </el-select>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" :icon="Search" @click="initData">查询</el-button>
                    <el-button :icon="Refresh" @click="reset(operateRef, initData)">重置</el-button>
                </el-form-item>
            </el-form>
        </div>
        <div class="tableblock">
            <div class="crudblock">
                <el-button type="primary" :icon="Plus" @click="handleDialog('新增菜单')">新增</el-button>
            </div>
            <el-table :data="tableData" row-key="_id" v-loading="loading">
                <el-table-column prop="name" label="菜单名称" align="center" min-width="150px" />
                <el-table-column prop="icon" label="图标" align="center" min-width="150px" />
                <el-table-column prop="type" label="菜单类型" align="center" min-width="80px">
                    <template #default="scope">
                        <span>{{ scope.row.type == 1 ? '菜单' : '按钮' }}</span>
                    </template>
                </el-table-column>
                <el-table-column prop="auth_ID" label="权限标识" align="center" min-width="150px" />
                <el-table-column prop="route_address" label="路由地址" align="center" min-width="150px" />
                <el-table-column prop="component_path" label="组件路径" align="center" min-width="150px" />
                <el-table-column prop="state" label="菜单状态" align="center" min-width="80px">
                    <template #default="scope">
                        <span>{{ scope.row.state == 1 ? '正常' : '停用' }}</span>
                    </template>
                </el-table-column>
                <el-table-column prop="create_time" label="创建时间" align="center" min-width="110px">
                    <template #default="scope">
                        <span>{{ formatDate(scope.row.create_time) }}</span>
                    </template>
                </el-table-column>
                <el-table-column label="操作" align="center" min-width="200px" fixed="right">
                    <template #default="scope">
                        <el-button :icon="Edit" @click="handleDialog('编辑菜单', scope.row)">编辑</el-button>
                        <el-popconfirm width="200px" @confirm="deleteFn(scope.row._id)" confirm-button-text="Yes" :icon="InfoFilled" icon-color="#F56C6C" title="确认是否删除?">
                            <template #reference>
                                <el-button type="danger" :icon="Delete">删除</el-button>
                            </template>
                        </el-popconfirm>
                    </template>
                </el-table-column>
            </el-table>
        </div>

        <!-- 表单对话框 -->
        <formDialog v-model:dialogState="dialogState" :dialogConfig="dialogConfig" :formConfig="formConfig" />
    </div>
</template>

<script setup>
import { Delete, Edit, Search, Plus, Refresh, InfoFilled } from '@element-plus/icons-vue'
import { reactive, computed, onBeforeUnmount, ref, watch } from 'vue'
import useTableList from '@/hooks/useTableList.js'
import formDialog from '@/components/formDialog.vue'
import { formatDate, flattenTree } from '@/utils/utils.js'
import { menuList, menuDelete, menuCreate, menuUpdate } from '@/api/index.js'
import mitt from '@/utils/mitt'
import store from '@/store/index.js';

let flattenMenuData = []
const operateRef = ref(null)
const state = reactive({
    formInline: {
        searchVal: '',
        state: 0
    }
})
let menuType = ref(null)
const { loading, initData, tableData, reset, dialogState, dialogConfig, handleDialog } = useTableList(menuList, state.formInline)

// 监听表单值改变
mitt.on('changeForm', res => {
    menuType.value = res.type
})

// 监听表单提交事件
mitt.on('submit', res => {
    onSubmit(res)
})

// 删除
const deleteFn = async (id) => {
    let res = await menuDelete({ id, parentID: getAllChildrenID(id) })
    initData()
    store.dispatch('getAsideMenu')
    ElMessage.success(res)
}

// 获取当前节点的所有子级 ID
const getAllChildrenID = (id) => {
    let curID = id
    const parentID = []

    function filterParent(id) {
        for (let i = 0; i < flattenMenuData.length; i++) {
            if (flattenMenuData[i].pid == id) {
                parentID.push(flattenMenuData[i]._id)
                filterParent(flattenMenuData[i]._id)
            }
        }
    }

    filterParent(curID)
    return parentID
}

// 创建 OR 编辑
const onSubmit = async (d) => {
    let res = dialogConfig.title == '新增菜单' ? await menuCreate(d) : await menuUpdate(d)
    initData()
    store.dispatch('getAsideMenu')
    dialogState.value = false
    ElMessage.success(res)
}

const menuConfig = [
    { label: '菜单图标', type: 'text', name: 'icon', props: { 'placeholder': '请输入菜单图标', } },
    { label: '路由地址', type: 'text', name: 'route_address', props: { 'placeholder': '请输入路由地址', } },
    { label: '组件路径', type: 'text', name: 'component_path', props: { 'placeholder': '请输入组件路径', } }
]

const btnConfig = [
    { label: '权限标识', type: 'text', name: 'auth_ID', props: { 'placeholder': '请输入权限标识', } }
]

let menuCascaderOptions = reactive([])
const formatCascader = (newV, oldV) => {
    // 使用深拷贝，防止修改原始数据 tableData 导致一直循环触发 watch 监听、以及污染原始数据
    menuCascaderOptions.length = 0
    menuCascaderOptions.push(...JSON.parse(JSON.stringify(newV)))
    // 将数据扁平化，给删除方法使用
    flattenMenuData = flattenTree(newV)

    getMenuTypeTree(menuCascaderOptions)
}

// 递归筛选出菜单类型数据
const getMenuTypeTree = (d) => {
    for (let i = 0; i < d.length; i++) {
        if (d[i].children && d[i].children.length > 0) {
            d[i].children = d[i].children.filter(e => e.type !== 2)
            if (d[i].children.length > 0) getMenuTypeTree(d[i].children);
        }
    }
}

watch(tableData, formatCascader, { deep: true })

const formConfig = computed(() => {
    const configObj = {
        labelWidth: '80px',
        rules: {
            name: [
                { required: true, message: '不能为空!', trigger: 'blur' },
            ],
            type: [
                { required: true, message: '请选择菜单类型!', trigger: 'blur' },
            ]
        },
        items: [
            {
                label: '父级菜单',
                type: 'cascader',
                name: 'pid',
                props: {
                    'options': menuCascaderOptions,
                    'show-all-levels': false,
                    'placeholder': '为空，则为一级菜单',
                    'clearable': true,
                    'disabled': dialogConfig.title == '编辑菜单' ? true : false,
                    'props': { emitPath: false, checkStrictly: true, value: '_id', label: 'name' }
                }
            },
            {
                label: '菜单类型',
                type: 'radio',
                name: 'type',
                defaultValue: 1,
                options: [
                    {
                        label: '菜单', value: 1, props: {
                            disabled: dialogConfig.title == '编辑菜单' ? true : false
                        }
                    },
                    {
                        label: '按钮', value: 2, props: {
                            disabled: dialogConfig.title == '编辑菜单' ? true : false
                        }
                    }
                ]
            },
            { label: '菜单名称', type: 'text', name: 'name', props: { 'placeholder': '请输入菜单名称', } },
            {
                label: '菜单状态',
                type: 'radio',
                name: 'state',
                defaultValue: 1,
                options: [
                    { label: '正常', value: 1 },
                    { label: '停用', value: 2 }
                ]
            }
        ]
    }

    // 删除原有的
    const startIndex = configObj.items.findIndex(item => item.label == '菜单名称') + 1
    const endIndex = configObj.items.findIndex(item => item.label == '菜单状态')
    configObj.items.splice(startIndex, endIndex - startIndex)

    // 根据类型添加表单配置
    if (menuType.value == 1) configObj.items.splice(startIndex, 0, ...menuConfig);
    else configObj.items.splice(startIndex, 0, ...btnConfig);

    return configObj
})

onBeforeUnmount(() => {
    mitt.off('changeForm')
    mitt.off('submit')
})

</script>

<style lang='scss' scoped>
.container {}
</style>